"""
Author        yongfa
Date          2022-07-05 15:41:54
LastEditTime  2023-07-06 17:31:33
LastEditors   yongfa
Description   功能描述
"""

import os
import time

from flask import Flask, g
from werkzeug.exceptions import BadRequest, HTTPException
from sqlalchemy.exc import IntegrityError, DataError, CompileError
from flask_sqlalchemy import get_debug_queries
from app.modules import configure_blueprints
from app.extensions import configure_extensions
from app.extensions.command import configure_cli
from app.extensions.exception import APIException, RepeatException, LimiterError, ServerError, DataformatError
from app.extensions.logger import configure_logging
from .config import configs


def create_app(config_name="default"):

    # 环境配置
    app_config = configs[os.getenv('APP_SETTINGS', config_name)]
    app_name = app_config.PROJECT_NAME
    # app_env = app_config.ENV
    static_folder = app_config.STATIC_FOLDER
    template_folder = app_config.TEMPLATES_FOLDER

    # 初始化应用
    app = Flask(app_name, static_folder=static_folder, template_folder=template_folder)
    app.config.from_object(app_config)

    configure_error(app)
    configure_extensions(app)
    configure_blueprints(app)
    configure_cli(app)
    configure_hook(app)
    configure_logging(app)

    return app


def configure_hook(app):
    """应用钩子"""

    @app.before_request
    def record_start_request():
        """记录请求开始时间"""
        g.request_start_time = time.time()

    @app.after_request
    def after_query_request(response):
        """查询时间阀值"""
        for query in get_debug_queries():
            if query.duration >= app.config['FLASKY_SLOW_DB_QUERY_TIME']:
                app.logger.warning(
                    'Slow query: %s\nParameters: %s\nDuration: %fs\nContext: %s\n'
                    % (query.statement, query.parameters, query.duration,
                       query.context))
        return response


def configure_error(app):
    @app.errorhandler(404)
    def not_found(e):
        app.logger.info(str(e))
        return APIException(error_code=1, message="url不存在")

    @app.errorhandler(429)
    def limiter_error(e):
        app.logger.info(str(e))
        return LimiterError(message=e.limit.error_message)

    @app.errorhandler(Exception)
    def framework_error(e):
        if isinstance(e, APIException):
            if isinstance(e, ServerError):
                app.logger.exception(str(e))  # 打印到日志
            return e
        elif isinstance(e, HTTPException):
            message = e.description
            if isinstance(e, BadRequest):  # 参数错误类
                message = str(e.data.get('errors')) if hasattr(e, 'data') else None
            return DataformatError(error_code=1, message=message)
        elif isinstance(e, IntegrityError):
            if 'duplicate' in str(e.orig).lower():
                return RepeatException(message='数据的unique字段重复,' + str(e.orig))
            else:
                return RepeatException(message='参数错误' + str(e.orig))
        elif isinstance(e, DataError):
            app.logger.exception(str(e))  # 打印到日志
            return RepeatException(message='参数格式错误！,' + str(e.orig))
        elif isinstance(e, CompileError):
            app.logger.exception(str(e))  # 打印到日志
            return RepeatException(message='批量插入异常 {}'.format(e.args))
        else:
            app.logger.exception(str(e))  # 打印到日志
            if not app.config['DEBUG']:
                return ServerError()  # 未知错误(统一为服务端异常)
            else:
                raise e
